#include "app_buffer.h"

/**
 * 初始化小缓冲区
 * @param buffer_size 小缓冲区大小
 * @return 小缓冲区指针
 */
static SubBuffer *app_sub_buffer_init(int buffer_size)
{
    // 申请小缓冲区
    SubBuffer *subBuffer = (SubBuffer *)malloc(sizeof(SubBuffer));
    // 初始化变量
    subBuffer->ptr = (unsigned char *)malloc(buffer_size);
    subBuffer->buffer_size = buffer_size;
    subBuffer->buffer_len = 0;
    return subBuffer;
}

/**
 * 初始化缓冲区
 * @param buffer_size 小缓冲区大小
 * @return 缓冲区指针
 */
Buffer *app_buffer_init(int buffer_size)
{
    // 申请缓冲区
    Buffer *buffer = (Buffer *)malloc(sizeof(Buffer));
    // 存放初始化两个小缓冲区
    buffer->subBuffer[0] = app_sub_buffer_init(buffer_size);
    buffer->subBuffer[1] = app_sub_buffer_init(buffer_size);
    buffer->read_index = 0;
    buffer->write_index = 1;
    // 初始化锁
    pthread_mutex_init(&buffer->read_mutex, NULL);
    pthread_mutex_init(&buffer->write_mutex, NULL);
    return buffer;
}
/**
 * 释放缓冲区
 * @param buffer 缓冲区指针
 */
void app_buffer_free(Buffer *buffer)
{
    free(buffer->subBuffer[0]->ptr);
    free(buffer->subBuffer[0]);
    free(buffer->subBuffer[1]->ptr);
    free(buffer->subBuffer[1]);
    free(buffer);
}
/**
 * @brief 切换缓冲区
 * @param buffer 缓冲区指针
 */
void app_buffer_switch(Buffer *buffer)
{
    // 切换缓冲区之前，加写锁
    log_debug("切换缓冲区之前，加写锁");
    pthread_mutex_lock(&buffer->write_mutex);
    int tmp = buffer->read_index;
    buffer->read_index = buffer->write_index;
    buffer->write_index = tmp;
    log_debug("切换缓冲区之前，解写锁");
    pthread_mutex_unlock(&buffer->write_mutex);
}
/**
 * 读取缓冲区数据
 * @param buffer 缓冲区指针
 * @param data_buf 缓冲区数据
 * @param size 要读到缓冲区的大小
 * @return 读取的数据长度, -1 读取失败
 */
int app_buffer_read(Buffer *buffer, char *data_buf, int size)
{
    // !加锁
    log_debug("读数据之前，加读锁");
    pthread_mutex_lock(&buffer->read_mutex);
    // !获取当前读取缓冲区
    SubBuffer *r_subBuffer = buffer->subBuffer[buffer->read_index];
    // !判断当前缓冲区是否为空，切换读写缓冲区
    if (r_subBuffer->buffer_len == 0)
    {
        app_buffer_switch(buffer);
        r_subBuffer = buffer->subBuffer[buffer->read_index];
        if (r_subBuffer->buffer_len == 0)
        {
            log_error("缓冲区已空，读取失败，解读锁");
            pthread_mutex_unlock(&buffer->read_mutex);
            return -1;
        }
    }
    // !读取数据
    // 读取数据长度
    int r_len = r_subBuffer->ptr[0];
    // 判断缓冲区大小够不够
    if (size < r_len)
    {
        log_error("缓冲区数据长度不够，读取失败，解读锁");
        pthread_mutex_unlock(&buffer->read_mutex);
        return -1;
    }
    // 读取数据
    memcpy(data_buf, r_subBuffer->ptr + 1, r_len);
    log_debug("读数据成功，解读锁");
    pthread_mutex_unlock(&buffer->read_mutex);
    // !更新缓冲区长度
    r_subBuffer->buffer_len -= r_len + 1;
    // !移动缓冲区数据
    memmove(r_subBuffer->ptr, r_subBuffer->ptr + r_len + 1, r_subBuffer->buffer_len);
    // 返回读取的长度
    return r_len;
}
/**
 * 写入缓冲区数据
 * @param buffer 缓冲区指针
 * @param data 要写入的数据
 * @param len 要写入的数据长度
 * @return 0 写入成功, -1 写入失败
 */
int app_buffer_write(Buffer *buffer, char *data, int len)
{
    // 写入的字节数不能多于255，因为一个字节最大表示的数字为255
    if (len > 255)
    {
        log_error("数据长度不能超过255字节，写入失败");
        return -1;
    }
    // !加锁
    log_debug("写入数据之前，加写锁");
    pthread_mutex_lock(&buffer->write_mutex);
    // !获取当前写入缓冲区
    SubBuffer *w_subBuffer = buffer->subBuffer[buffer->write_index];
    // !判断当前写入缓冲区是否已满
    if (w_subBuffer->buffer_len + len + 1 > w_subBuffer->buffer_size)
    {
        log_error("写入缓冲区已满，写入失败，解写锁");
        pthread_mutex_unlock(&buffer->write_mutex);
        return -1;
    }
    // !向写缓冲区写入数据
    // 写入数据长度len
    w_subBuffer->ptr[w_subBuffer->buffer_len] = len;
    // 写入数据
    memcpy(w_subBuffer->ptr + w_subBuffer->buffer_len + 1, data, len);
    log_debug("写入数据成功，解写锁");
    pthread_mutex_unlock(&buffer->write_mutex);
    // !更新缓冲区长度
    w_subBuffer->buffer_len += len + 1;
    return 0;
}
